/**
 Author: 蒋鑫强
 Time: 2023/6/5
 Description:
 */
import util, {DateUtil} from '@/util/util';
const tinify = require('tinify');
const { Buffer } = require('node:buffer');
const fs = require('node:fs');
tinify.key = "Kg3wZ7dMTp0Xcp5Y6lprk1nKGJDtz8vB";

export default {
  zipBuffer(bufferData) {
    return new Promise((resolve, reject) => {
      tinify.fromBuffer(bufferData).toBuffer((err, resultData) => {
        if (err) {
          console.error(err);
          reject();
        } else {
          resolve(resultData);
        }
      });
    });
  },

  saveFile(path, data) {
    return new Promise((resolve, reject) => {
      fs.writeFile(path, data, (err, resultData) => {
        if (err) {
          console.error(err);
          reject();
        } else {
          resolve(resultData);
        }
      });
    });
  },

  getFileSize(path) {
    return new Promise(resolve => {
      fs.stat(path, (err, status) => {
        resolve(status.size);
      });
    });
  },

  async zip(file) {
    const res = await this.hasAlpha(file.url);
    let fileName = file.name;
    let path = `tmp/${util.getRandomStr(8)}-${fileName}`;
    const sourceSizeDisplay = this.bytesToSize(file.size);
    if (res) {
      //png
      const source = tinify.fromFile(file.raw.path);
      await source.toFile(path);
      const targetSize = await this.getFileSize(path);
      return {
        sourceSize: file.size,
        sourceSizeDisplay,
        targetSize,
        targetSizeDisplay: this.bytesToSize(targetSize),
        url: path,
        name: fileName,
        createTime: DateUtil.format(new Date(), 'yyyy-MM-dd hh:mm:ss')
      };
    } else {
      //jpg
      const reqData = await this.toJpg(file.url);
      const dataMiniURLBase64 = reqData.replace(/^data:image\/\w+;base64,/, '');
      const dataMiniBuffer = Buffer.from(dataMiniURLBase64, 'base64');
      const resultData = await this.zipBuffer(dataMiniBuffer);
      fileName = fileName.replace('.png', '.jpg');
      path = path.replace('.png', '.jpg');
      await this.saveFile(path, resultData);
      const targetSize = await this.getFileSize(path);
      return {
        sourceSize: file.size,
        sourceSizeDisplay,
        targetSize,
        targetSizeDisplay: this.bytesToSize(targetSize),
        url: path,
        name: fileName,
        createTime: DateUtil.format(new Date(), 'yyyy-MM-dd hh:mm:ss')
      };
    }
  },

  async toJpg(url) {
    const { canvas } = await this.loadImg(url);
    return canvas.toDataURL('image/jpeg', 0.8);
  },

  async hasAlpha(url) {
    const { imageData } = await this.loadImg(url);
    let isAlphaBackground = false;
    for (let index = 3; index < imageData.length; index += 4) {
      if (imageData[index] !== 255) {
        isAlphaBackground = true;
        break;
      }
    }
    return isAlphaBackground;
  },

  loadImg(url) {
    return new Promise(resolve => {
      const img = new Image();
      img.crossOrigin = '';
      const canvas = document.createElement('canvas');
      const ctx = canvas.getContext('2d');
      img.onload = () => {
        canvas.width = img.width;
        canvas.height = img.height;
        ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
        const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height).data;
        resolve({
          imageData,
          canvas,
          ctx
        });
      }
      img.src = url;
    });
  },

  removeFile(list) {
    list.forEach(d => {
      fs.unlink(d.url, (err) => {
        if (err) {
          console.error(err);
        }
      });
    });
  },

  bytesToSize(bytes) {
    if (bytes === 0) {return '0 B';}
    let k = 1024;
    let sizes = ['B','KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
    let i = Math.floor(Math.log(bytes) / Math.log(k));
    return (bytes / Math.pow(k, i)).toFixed(1) + ' ' + sizes[i];
  },
};
